﻿using System;
using Glue;
using Glue.Internals.Verification;
using Xunit;

namespace GlueTests
{
    public class RandomizerTest
    {
        private enum EnumMustBeRandomized
        {
            First,
            Second,
            Third,
            Fourth
        }

        private readonly Randomizers randomizer;

        public RandomizerTest()
        {
            randomizer = new Randomizers();
        }

        [Fact]
        public void Should_not_randomize_Objects()
        {
            Assert.Throws(typeof(GlueException), () => randomizer.GetRandomValue(typeof(RandomizerTest)));
        }

        [Fact]
        public void Should_randomize_enums()
        {
            AssertRandomizes<EnumMustBeRandomized>();
        }

        [Fact]
        public void Should_randomize_DateTime()
        {
            AssertRandomizes<DateTime>();
        }

        [Fact]
        public void Should_randomize_nullable_DateTime()
        {
            AssertRandomizes<DateTime?>();
        }

        [Fact]
        public void Should_randomize_boolean()
        {
            AssertRandomizes<bool>();
        }

        [Fact]
        public void Should_randomize_nullable_boolean()
        {
            AssertRandomizes<bool?>();

        }

        [Fact]
        public void Should_randomize_byte()
        {
            AssertRandomizes<byte>();
        }

        [Fact]
        public void Should_randomize_nullable_byte()
        {
            AssertRandomizes<byte?>();
        }

        [Fact]
        public void Should_randomize_sbyte()
        {
            AssertRandomizes<sbyte>();
        }

        [Fact]
        public void Should_randomize_nullable_sbyte()
        {
            AssertRandomizes<sbyte?>();
        }

        [Fact]
        public void Should_randomize_char()
        {
            AssertRandomizes<char>();
        }

        [Fact]
        public void Should_randomize_nullable_char()
        {
            AssertRandomizes<char?>();
        }

        [Fact]
        public void Should_randomize_decimal()
        {
            AssertRandomizes<decimal>();
        }

        [Fact]
        public void Should_randomize_nullable_decimal()
        {
            AssertRandomizes<decimal?>();
        }

        [Fact]
        public void Should_randomize_double()
        {
            AssertRandomizes<double>();
        }

        [Fact]
        public void Should_randomize_nullable_double()
        {
            AssertRandomizes<double?>();
        }

        [Fact]
        public void Should_randomize_float()
        {
            AssertRandomizes<float>();
        }

        [Fact]
        public void Should_randomize_nullable_float()
        {
            AssertRandomizes<float?>();
        }

        [Fact]
        public void Should_randomize_int()
        {
            AssertRandomizes<int>();
        }

        [Fact]
        public void Should_randomize_nullable_int()
        {
            AssertRandomizes<int?>();
        }

        [Fact]
        public void Should_randomize_uint()
        {
            AssertRandomizes<uint>();
        }

        [Fact]
        public void Should_randomize_nullable_uint()
        {
            AssertRandomizes<uint?>();
        }

        [Fact]
        public void Should_randomize_long()
        {
            AssertRandomizes<long>();
        }

        [Fact]
        public void Should_randomize_nullable_long()
        {
            AssertRandomizes<long?>();
        }

        [Fact]
        public void Should_randomize_ulong()
        {
            AssertRandomizes<ulong>();
        }

        [Fact]
        public void Should_randomize_nullable_ulong()
        {
            AssertRandomizes<ulong?>();
        }

        [Fact]
        public void Should_randomize_short()
        {
            AssertRandomizes<short>();
        }

        [Fact]
        public void Should_randomize_nullable_short()
        {
            AssertRandomizes<short?>();
        }

        [Fact]
        public void Should_randomize_ushort()
        {
            AssertRandomizes<ushort>();
        }

        [Fact]
        public void Should_randomize_nullable_ushort()
        {
            AssertRandomizes<ushort?>();
        }

        [Fact]
        public void Should_randomize_String()
        {
            AssertRandomizes<String>();
        }

        private void AssertRandomizes<T>()
        {
            Assert.True(AllNotEqual(() => randomizer.GetRandomValue(typeof(T))));
        }

        private bool AllNotEqual(Func<object> func)
        {
            var value = func();
            for (int i =0;i<10;i++)
            {
                var newValue = func();
                if (value!=newValue)
                    return true;
            }
            return false;
        }    
        
    }
}
